/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkRtpServerPool.h"
#include "MkEvent/MkEventPool.h"
#include "MkRtpUdpServer.h"
#include "MkRtpTcpServer.h"
#include "MkUtil/MkLog.h"
#include "MkUtil/MkUtil.h"

CMkRtpServerPool::CMkRtpServerPool(CMkEventPool *pEventPool, CMkTimer* pTimer)
    : m_pEventPool(pEventPool)
    , m_pTimer(pTimer)
    , m_BeginPort(60000)
    , m_EndPort(0)
{

}

Uint32 CMkRtpServerPool::Start()
{
    MkVector<CMkEvent*>::iterator it = m_pEventPool->GetVecEvent().begin();
    Uint16 OffsetPort = m_BeginPort;
    for (; it != m_pEventPool->GetVecEvent().end(); it++) {
        do {
            CMkRtpUdpServer *pUdpServer = CreateRtpUdpServer(*it, OffsetPort);
            CMkRtpTcpServer *pTcpServer = CreateRtpTcpServer(*it, OffsetPort);
            OffsetPort += 2;
            if (pUdpServer && pTcpServer) {
                m_VecUdpServer.emplace_back(pUdpServer);
                m_VecTcpServer.emplace_back(pTcpServer);
                m_VecPairRtpServer.emplace_back(MkPair<CMkRtpTcpServer*, CMkRtpUdpServer*>(pTcpServer, pUdpServer));
                m_EndPort = pUdpServer->GetRtcpPort();
                break;
            } else {
                MkDelete(pUdpServer);
                MkDelete(pTcpServer);
            }
        } while (1);
    }
    MkInfoLog("start rtp pool begin port:%d endport:%d success\n", m_BeginPort, m_EndPort);
    return NoneError;
}

CMkRtpUdpServer* CMkRtpServerPool::CreateRtpUdpServer(CMkEvent* pEvent, const Uint16& UdpPort)
{
    CMkRtpUdpServer *pUdpServer = new CMkRtpUdpServer(pEvent, m_pTimer);
    if (!pUdpServer) {
        return nullptr;
    }
    Uint16 ErrorCode = pUdpServer->Start(UdpPort);
    if (NoneError != ErrorCode) {
        MkDelete(pUdpServer);
        return nullptr;
    }
    return pUdpServer;
}

CMkRtpTcpServer* CMkRtpServerPool::CreateRtpTcpServer(CMkEvent* pEvent, const Uint16& TcpPort)
{
    CMkRtpTcpServer *pTcpServer = new CMkRtpTcpServer(m_pEventPool, m_pTimer);
    if (!pTcpServer) {
        return nullptr;
    }
    Uint16 ErrorCode = pTcpServer->StartServer(TcpPort);
    if (NoneError != ErrorCode) {
        MkDelete(pTcpServer);
        return nullptr;
    }
    return pTcpServer;
}

Uint32 CMkRtpServerPool::Stop()
{
    return NoneError;
}

CMkRtpUdpServer* CMkRtpServerPool::GetFreeUdpServer()
{
    Uint32 nMaxScore = 0;
    CMkRtpUdpServer* pUdpServer = nullptr;
    MkVector<CMkRtpUdpServer*>::iterator it = m_VecUdpServer.begin();
    for (; it != m_VecUdpServer.end(); it++) {
        if ((*it)->GetScore() > nMaxScore) {
            pUdpServer = *it;
            nMaxScore = (*it)->GetScore();
        }
    }
    return pUdpServer;
}

CMkRtpTcpServer* CMkRtpServerPool::GetFreeTcpServer()
{
    Uint32 nMaxScore = 0;
    CMkRtpTcpServer* pTcpServer = nullptr;
    MkVector<CMkRtpTcpServer*>::iterator it = m_VecTcpServer.begin();
    for (; it != m_VecTcpServer.end(); it++) {
        if ((*it)->GetScore() > nMaxScore) {
            pTcpServer = *it;
            nMaxScore = (*it)->GetScore();
        }
    }
    return pTcpServer;
}

MkPair<CMkRtpTcpServer*, CMkRtpUdpServer*> CMkRtpServerPool::GetFreeRtpServer() const
{
    Uint32 nMaxScore = 0;
    MkPair<CMkRtpTcpServer*, CMkRtpUdpServer*> Res;
    MkVector<MkPair<CMkRtpTcpServer*, CMkRtpUdpServer*>>::const_iterator it = m_VecPairRtpServer.begin();
    for (; it != m_VecPairRtpServer.end(); it++) {
        Uint32 CurScore = it->first->GetScore() > it->second->GetScore() ? it->second->GetScore() : it->first->GetScore();
        MkDebugLog("get cur score:%d\n", CurScore);
        if (CurScore > nMaxScore) {
            Res = *it;
            nMaxScore = CurScore;
        }
    }
    return Res;
}

CMkRtpServerPool::~CMkRtpServerPool()
{
    MkVector<CMkRtpUdpServer*>::iterator it = m_VecUdpServer.begin();
    for (; it != m_VecUdpServer.end(); it++) {
        MkDelete(*it);
    }
    m_VecUdpServer.clear();

    MkVector<CMkRtpTcpServer*>::iterator itTcp = m_VecTcpServer.begin();
    for (; itTcp != m_VecTcpServer.end(); itTcp++) {
        MkDelete(*itTcp);
    }
    m_VecTcpServer.clear();
}